package study.spring.mvc;

import java.io.File;
import javax.servlet.ServletContext;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.core.AprLifecycleListener;
import org.apache.catalina.startup.Tomcat;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import study.spring.mvc.nouseservlet.SpringMvcNoWebConfig;
import study.spring.mvc.useservlet.MyWebApplicationInitializer;
import study.spring.mvc.useservlet.SpringMvcConfig;

public class TestEmbedTomcat {

  public static String TOMCAT_HOSTNAME = "127.0.0.1";
  public static String WEBAPP_PATH = "spring-mvc/src/main";
  public static String WEBINF_CLASSES = "/WEB-INF/classes";
  public static String CLASS_PATH = "target/classes";
  public static String INTERNAL_PATH = "/";

  public static void main(String[] args) throws LifecycleException {
    tomcatUseContext();
//    tomcatUseWebApp();
  }

  /**
   * 1. 使用 embed tomcat 的 addContext 把项目看成一个普通项目, 然后手动添加 servlet
   * <p>
   * 不用再调用 {@link MyWebApplicationInitializer#onStartup(ServletContext)} 方法了
   * <p>
   * 注意 {@link SpringMvcConfig} 不能添加 @EnableWebMvc 注解
   */
  public static void tomcatUseContext() throws LifecycleException {


    AnnotationConfigWebApplicationContext webApplicationContext = new AnnotationConfigWebApplicationContext();
    // 注意这里的 SpringMvcNoWebConfig 不能有 EnableWebMvc注解, 因为当前的不是一个标准的 web环境
    webApplicationContext.register(SpringMvcNoWebConfig.class);
    webApplicationContext.refresh();
    DispatcherServlet dispatcherServlet = new DispatcherServlet(webApplicationContext);

    Tomcat tomcat = new Tomcat();
    tomcat.setPort(8089);
    tomcat.setBaseDir(".");
    String docBase = System.getProperty("user.dir") + File.separator + WEBAPP_PATH;
    Context context = tomcat.addContext("", docBase);

    context.setReloadable(false);
    // 上下文监听器
    context.addLifecycleListener(new AprLifecycleListener());


    // 注册servlet,  必须添加 setLoadOnStartup(0) 这样才会在 tomcat启动后立即执行 dispatcherServlet 的 init 方法
    tomcat.addServlet("", "dispatcherServlet", dispatcherServlet).setLoadOnStartup(0);
    context.addServletMappingDecoded("/*", "dispatcherServlet");
    tomcat.start();
    tomcat.getServer().await();

  }

  /**
   * 1. 使用 embed tomcat 的 addWebapp 把项目添加为一个 web 项目, 可以使用 servlet相关规范
   * <p>
   * 这里用到了一个servlet3.0的新规范: {@link MyWebApplicationInitializer#onStartup(ServletContext)} 参考 spring-mvc.md 文件
   * <p>
   * 下面的写法, 不适用于 tomcat 9 , TODO 探究下 embed tomcat9如何启动
   */
  public static void tomcatUseWebApp() throws LifecycleException {

    Tomcat tomcat = new Tomcat();
    tomcat.setPort(8090);
    // tomcat 信息保存在项目下
    tomcat.setBaseDir(".");
    String docBase = System.getProperty("user.dir") + File.separator + WEBAPP_PATH;
    Context context = tomcat.addWebapp("", docBase);
//    Context context = tomcat.addWebapp("/", System.getProperty("java.io.tmpdir"));
    /*
      setReloadable(false) ：相关 classes | jar 修改时，会重新加载资源，不过资源消耗很大
      autoDeploy 与这个很相似，tomcat自带的热部署不是特别可靠，效率也不高。生产环境不建议开启。
      相关文档： http://www.blogjava.net/wangxinsh55/archive/2011/05/31/351449.html
     */
    context.setReloadable(false);
    // 上下文监听器
    context.addLifecycleListener(new AprLifecycleListener());

    tomcat.start();
    tomcat.getServer().await();
  }


}
